package com.xuetang9.service.sn.impl;

import com.xuetang9.BO.CodeLengthBO;
import com.xuetang9.BO.RedisDO;
import com.xuetang9.BO.ResultMessageBO;
import com.xuetang9.Query.AccountLoginQuery;
import com.xuetang9.Query.PhoneAccountQuery;
import com.xuetang9.dao.UserMapper;
import com.xuetang9.dto.sn.MessageDTO;
import com.xuetang9.dto.sn.StateCode;
import com.xuetang9.dto.sn.VerificationCodeMessageDTO;
import com.xuetang9.service.sn.LoginService;
import com.xuetang9.utils.LoggerUtils;
import com.xuetang9.utils.sn.JacksonUtils;
import com.xuetang9.utils.sn.PhoneCodeSDK;
import com.xuetang9.utils.sn.PhoneLoginUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xuetang9.domain.User;

import java.util.Date;
import java.util.Map;
import java.util.UUID;


/**
 * @类: LoginServiceImpl
 * @描述: 登录服务实体类
 * @date: 2020/5/11
 * @author: Admin
 * @ver 1.0.0
 * @since JDK 1.8
 */
@Service
public class LoginServiceImpl implements LoginService {

    /**
     * 获取解密信息时对应的参数（手机号），可以每次启动服务器自动生成
     */
    private static final String DECRYPT_MESSAGE_PARAM_PHONE = "phone";

    UserMapper userMapper;

    @Autowired
    public LoginServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public User login(User user) {
        User user1 = userMapper.selectOne(user);
        if (user1 != null) {
            user.setPassword("");
            return user1;
        }
        return null;
    }

    @Override
    public MessageDTO login(AccountLoginQuery accountLoginQuery) {
        MessageDTO messageDTO = new MessageDTO();
        //获取用户输入的账号密码
        String account= accountLoginQuery.getAccount();
        String pass = accountLoginQuery.getPassword();
        //1.进行账号密码验证（模拟从数据库中查询数据）
        User userQuery = new User();
        userQuery.setAccount(account);
        User user = userMapper.selectOne(userQuery);
        if (user == null) {
            messageDTO.setFlag(false);
            messageDTO.setMessage("账号不存在！");
            messageDTO.setCode(StateCode.NOT_FIND);
            return messageDTO;
        }
        if (!pass.equals(user.getPassword())) {
            //不相等
            messageDTO.setFlag(false);
            messageDTO.setMessage("账号或密码错误！");
            messageDTO.setCode(StateCode.NOT_FIND);
            return messageDTO;
        }
        //2.组装信息
        //2.1 生成token
        String token = UUID.randomUUID().toString();
        //2.2 存入redis（模拟存入redis）
        RedisDO.recordUser(token,user);
        RedisDO.recordUser(token,new Date());
        //2.3 组装信息
        messageDTO.setFlag(true);
        messageDTO.setMessage("登录成功");
        messageDTO.setToken(token);
        messageDTO.setCode(StateCode.SUCCESS);
        return messageDTO;
    }

    @Override
    public String createCodeWithNumber(int codeLength) {
        StringBuilder codeBuilder = new StringBuilder();
        //随机数范围
        int numRange = 10;
        for (int i = 0; i < codeLength; i++) {
            int randomNum = (int) (Math.random() * numRange);
            codeBuilder.append(randomNum);
        }
        return codeBuilder.toString();
    }

    @Override
    public VerificationCodeMessageDTO getCode(String phone, CodeLengthBO codeLength) {
        //创建返回信息对象
        VerificationCodeMessageDTO verificationCodeMessageDTO = new VerificationCodeMessageDTO();
        //生成验证码
        String verificationCode = createCodeWithNumber(codeLength.getLength());
        try {
            //发送验证码
            String result = PhoneCodeSDK.sendCode(phone,verificationCode);
            //讲返回的json字符串转通过jackson换成对象来进行操作
            ResultMessageBO resultMessageBO = JacksonUtils.getMessageBO(result, ResultMessageBO.class);
            LoggerUtils.debug("发送完验证码返回的信息：{}",resultMessageBO);
            //根据结果返回相应信息
            if (resultMessageBO.getSuccess()) {
                verificationCodeMessageDTO.setFlag(true);
//                verificationCodeMessageDTO.setVerificationCode(verificationCode);
                verificationCodeMessageDTO.setCodeLength(codeLength.getLength());
                verificationCodeMessageDTO.setInformation(PhoneLoginUtils.encryptionPhoneAndTime(phone));
                //存入redis数据库（模拟）
                RedisDO.setValue(phone, verificationCode);
            } else {
                verificationCodeMessageDTO.setFlag(false);
                verificationCodeMessageDTO.setVerificationCode("发送失败！");
            }
        } catch (Exception e) {
            LoggerUtils.error("发送验证码出现异常，异常信息：{}",e.getMessage());
        }
        return verificationCodeMessageDTO;
    }

    @Override
    public VerificationCodeMessageDTO getCode(String phone) {
        return this.getCode(phone, CodeLengthBO.FOUR);
    }


    @Override
    public MessageDTO phoneLogin(PhoneAccountQuery phoneAccountQuery) throws Exception {
        MessageDTO messageDTO = new MessageDTO();
        //1.进行信息解密
        Map<String, String> message = PhoneLoginUtils.decryptMessage(phoneAccountQuery.getInformation(),DECRYPT_MESSAGE_PARAM_PHONE);
        if (message.containsKey(PhoneLoginUtils.ERROR)) {
            //用户传入加密的信息不正确
            messageDTO.setFlag(false);
            messageDTO.setMessage(message.get(PhoneLoginUtils.ERROR));
            return messageDTO;
        }
        //获取信息
        String phone = phoneAccountQuery.getPhone();
        String code = phoneAccountQuery.getVerificationCode();
        String phoneInfo = message.get(DECRYPT_MESSAGE_PARAM_PHONE);
        String timeInfo = message.get(PhoneLoginUtils.DECRYPT_MESSAGE_PARAM_TIME);
        //2.判断两次手机是否相同
        if (!phone.equals(phoneInfo)) {
            //手机号不同
            messageDTO.setFlag(false);
            messageDTO.setMessage("两次请求手机号不同！");
            return messageDTO;
        }
        //3.判断验证码是否过期
        if (RedisDO.isExpired(timeInfo)) {
            //验证码过期
            messageDTO.setFlag(false);
            messageDTO.setMessage("验证码已过期，请重新请求！");
            return messageDTO;
        }
        //4.判断验证码是否相同
        String localCode = RedisDO.getValue(phone);
        if (!localCode.equals(code)) {
            //两次验证码不同
            messageDTO.setFlag(false);
            messageDTO.setMessage("验证码不同，请重新请求！");
            return messageDTO;
        }
        //5.判断是否有该账号
        User userQuery = new User();
        userQuery.setEmail(phone);
        User user = userMapper.selectOne(userQuery);
        if (user != null ) {
            //存在
            //2.组装信息
            //2.1 生成token
            String token = UUID.randomUUID().toString();
            //2.2 存入redis（模拟存入redis）
            RedisDO.recordUser(token,user);
            RedisDO.recordUser(token,new Date());
            //2.3设置信息返回
            messageDTO.setFlag(true);
            messageDTO.setToken(token);
            messageDTO.setMessage("登录成功！");
        }else {
            //不存在
            messageDTO.setFlag(false);
            messageDTO.setMessage("账号不存在，请先注册！");
            messageDTO.setCode(StateCode.NOT_FIND);
        }
        return messageDTO;
    }


}
